AWS Step Functionsで、音声ファイルがS3バケットに保存される度にAmazon Transcribeで文字起こしし、内容をメール送信してみた
はじめに
AWS Step Functionsを利用し、音声ファイルがS3バケットに保存されるたびにAmazon Transcribeで文字起こしを行い、文字起こし内容をメール送信する方法を紹介します。
今回構築する構成は以下の通りです。
処理の流れは以下の通りです。
- 音声ファイル(WAV)をS3バケットにアップロードする
- アップロードをトリガーにEventBridgeからStep Functionsステートマシンを起動する
- 音声ファイルからAmazon Transcribeで文字起こしし、文字起こした内容をAmazon SNSでメール送信する
この構成を構築するきっかけは、以前執筆した「Amazon Connectでエージェントの介在がない場合でも電話中の発話を録音する」記事の構成に、録音ファイルに対して文字起こしとメール通知機能を追加する必要が生じたためです。
執筆した記事の構成図は以下の通りです。
今回新たに必要となった構成は以下の図の通りです。
今回は、S3バケットへの音声ファイルの保存をトリガーとし、文字起こしからメール通知までの一連の処理をStep Functions ステートマシンでコントロールします。
以下の順序でAWSリソースを作成していきます。
- SNSトピック作成
- S3バケット作成
- IAMポリシー作成
- ステートマシン作成
- EventBridgeルール作成
SNSトピック作成
SNSのメール通知の本文には通知を停止するリンクが記載されています。このリンクをクリックすると登録解除(Unsubscribe)されてしまうため、今回はこの登録解除を無効にする設定を行います。詳細は以下の記事をご参照ください。
SNSトピックは、タイプをスタンダードにし、名前を記載します。ほかはデフォルトとしてます。
サブスクリプションをプロトコルをEメールにして作成します。
登録したメールアドレスに対して、件名[AWS Notification - Subscription Confirmation]というメールが届きます。
以下の赤枠の[Confirm subscription]というリンクを右クリックして、リンクのアドレスをコピーします。
コピーしたリンクの内容は以下の通りです。この中からToken
の値(aaaaaaaaa)をコピーしてください。
https://sns.ap-northeast-1.amazonaws.com/confirmation.html?TopicArn=arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai&Token=aaaaaaaaa&Endpoint=test@example.com
AWSマネジメントコンソールからCloudShellを開き、以下のコマンドを実行します。
コマンド中の[SNSトピックARN]と[Token]の部分を、それぞれ実際の値に置き換えてください。
$ aws sns confirm-subscription \
--topic-arn arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai \
--token aaaaaaaaa \
--authenticate-on-unsubscribe true \
--region ap-northeast-1
{
"SubscriptionArn": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai:xxxxxx"
}
$ aws sns get-subscription-attributes\
--subscription-arn arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai:xxxxxx
{
"Attributes": {
"SubscriptionPrincipal": "arn:aws:iam::xxxxxxxxxxxx:role/xxxx",
"Owner": "xxxxxxxxxxxx",
"RawMessageDelivery": "false",
"TopicArn": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai",
"Endpoint": "test@example.com",
"Protocol": "email",
"PendingConfirmation": "false",
"ConfirmationWasAuthenticated": "true",
"SubscriptionArn": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai:xxxxxx"
}
}
ConfirmationWasAuthenticated
属性の値がtrueになれば、メール本文からは登録解除が行われません。
設定したSNSトピックからメールを送ってみます。
メール受信されたことを確認します。また、メールに記載された登録解除のリンクをクリックしてみます。
リンクをクリックしても、登録解除できないことが確認できます。
これでSNSトピック設定完了です。
S3バケット作成
以下のS3バケットを2つ作成します。
- 音声ファイル保存用(cm-hirai-audio-for-transcription)
- 文字起こししたテキストファイルを保存用(cm-hirai-transcription-output)
バケット名以外の設定はすべてデフォルトのままとしています。
作成後、音声ファイル保存用(cm-hirai-audio-for-transcription)S3バケットのプロパティタブから、[このバケット内のすべてのイベントについて Amazon EventBridge に通知を送信する]を有効にします。
有効にすると、変更が適用されるまで約 5 分かかります。
EventBridge に送信される Amazon S3 イベント通知メッセージの例は、以下の通りです。このメッセージは、ステートマシンの実行時の入力としても渡されます。
{
"version": "0",
"id": "17793124-05d4-b198-2fde-7ededc63b103",
"detail-type": "Object Created",
"source": "aws.s3",
"account": "111122223333",
"time": "2021-11-12T00:00:00Z",
"region": "ca-central-1",
"resources": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET1"
],
"detail": {
"version": "0",
"bucket": {
"name": "DOC-EXAMPLE-BUCKET1"
},
"object": {
"key": "example-key",
"size": 5,
"etag": "b1946ac92492d2347c6235b4d2611184",
"version-id": "IYV3p45BT0ac8hjHg1houSdS1a.Mro8e",
"sequencer": "617f08299329d189"
},
"request-id": "N4N7GDK58NMKJ12R",
"requester": "123456789012",
"source-ip-address": "1.2.3.4",
"reason": "PutObject"
}
}
IAMポリシー作成
ステートマシン用のIAMポリシーを作成します。
以下の権限を持つポリシーを「cm-hirai-notify-transcription-policy」という名前で作成します。なお、アカウントIDは各自の環境に合わせて変更してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::cm-hirai-transcription-output/*"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::cm-hirai-transcription-output/*",
"arn:aws:s3:::cm-hirai-audio-for-transcription/*"
]
},
{
"Effect": "Allow",
"Action": "transcribe:GetTranscriptionJob",
"Resource": "arn:aws:transcribe:ap-northeast-1:xxxxxxxxxxxx:transcription-job/*"
},
{
"Effect": "Allow",
"Action": "transcribe:StartTranscriptionJob",
"Resource": "*"
}
]
}
SNSのメール送信の権限は、ステートマシン作成時に自動生成されるIAMロールとポリシーに自動で追加されるため、このポリシーには含めません。
ステートマシン作成
Step Functions のステートマシンを作成します。
まず、ステートマシンの画面からコードタブに移動し、以下のJSONコードを貼り付けます。
{
"Comment": "Audio transcription and notification workflow",
"StartAt": "StartTranscriptionJob",
"States": {
"StartTranscriptionJob": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:transcribe:startTranscriptionJob",
"Parameters": {
"TranscriptionJobName.$": "$$.Execution.Name",
"LanguageCode": "ja-JP",
"Media": {
"MediaFileUri.$": "States.Format('s3://{}/{}', $.detail.bucket.name, $.detail.object.key)"
},
"OutputBucketName": "cm-hirai-transcription-output",
"OutputKey.$": "States.Format('{}.json', $$.Execution.Name)",
"Settings": {
"ShowSpeakerLabels": true,
"MaxSpeakerLabels": 2
}
},
"ResultPath": "$.TranscriptionJob",
"Next": "Wait"
},
"Wait": {
"Type": "Wait",
"Seconds": 1,
"Next": "GetTranscriptionJob"
},
"GetTranscriptionJob": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:transcribe:getTranscriptionJob",
"Parameters": {
"TranscriptionJobName.$": "$.TranscriptionJob.TranscriptionJob.TranscriptionJobName"
},
"ResultPath": "$.GetTranscriptionJobResult",
"Next": "CheckStatus"
},
"CheckStatus": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.GetTranscriptionJobResult.TranscriptionJob.TranscriptionJobStatus",
"StringEquals": "COMPLETED",
"Next": "GetTranscriptionContent"
},
{
"Variable": "$.GetTranscriptionJobResult.TranscriptionJob.TranscriptionJobStatus",
"StringEquals": "FAILED",
"Next": "TranscriptionJobFailed"
}
],
"Default": "Wait"
},
"GetTranscriptionContent": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:s3:getObject",
"Parameters": {
"Bucket": "cm-hirai-transcription-output",
"Key.$": "States.Format('{}.json', $.GetTranscriptionJobResult.TranscriptionJob.TranscriptionJobName)"
},
"ResultSelector": {
"Content.$": "States.StringToJson($.Body)"
},
"ResultPath": "$.TranscriptionContent",
"Next": "PrepareNotification"
},
"PrepareNotification": {
"Type": "Pass",
"Parameters": {
"subject": "【自動通知】音声ファイルの文字起こし完了",
"message.$": "States.Format('音声ファイルが保存されましたので、文字起こし内容をお知らせいたします。\n\n■ トランスクリプションジョブ詳細\n・TranscribeジョブとStep Functionsステートマシン実行名: {}\n・音声ファイル: s3://{}/{}\n・文字起こしテキストファイル: s3://cm-hirai-transcription-output/{}.json\n\n■ 文字起こし内容\n{}\n\n■ 注意事項\n1. 上記の文字起こし内容は自動生成されたものです。正確性を要する場合は、音声ファイルの内容をご確認ください。\n2. 音声ファイルと文字起こしテキストファイルは、それぞれ指定されたS3バケット内に保存されています。必要に応じてダウンロードしてご利用ください。\n\n本通知は自動生成されています。\nご不明な点やお問い合わせは、システム管理者までご連絡ください。', $.GetTranscriptionJobResult.TranscriptionJob.TranscriptionJobName, $.detail.bucket.name, $.detail.object.key, $.GetTranscriptionJobResult.TranscriptionJob.TranscriptionJobName, $.TranscriptionContent.Content.results.transcripts[0].transcript)"
},
"Next": "SendNotification"
},
"SendNotification": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicArn": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai",
"Subject.$": "$.subject",
"Message.$": "$.message"
},
"Next": "TranscriptionJobSucceeded"
},
"TranscriptionJobSucceeded": {
"Type": "Succeed"
},
"TranscriptionJobFailed": {
"Type": "Fail",
"Cause": "Transcription job failed",
"Error": "TranscriptionJobFailedException"
}
}
}
- 以下は、各自の環境に合わせて変更してください。
TopicArn
:SNSトピックARNOutputBucketName
:文字起こししたテキストファイルを保存するS3バケット名
- Transcribeジョブ名と文字起こしした内容をS3バケットに保存するテキストファイル名は、ステートマシン実行名と同一にしています。
- ステートマシン実行名は、ステートマシンやその実行に関する情報を含むコンテキストオブジェクトから取得しています。
- Pass state(PrepareNotification)で、メール本文を作成していますので、必要に応じて修正ください。
作成されるステートマシンのワークフローは以下の図の通りです。
設定タブに移動し、ステートマシン名を入力します。
画面右上の「作成」ボタンをクリックします。
IAMロールは自動的に作成されますが、TranscribeやS3へのアクセス権限は自動では付与されないため、手動で追加する必要があります。
ステートマシンの作成後、自動生成されたIAMロールを確認すると、SNSへのアクセス権限用のIAMポリシーは自動作成されていました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai"
}
]
}
ステートマシンに自動生成されたIAMロールに、先ほど作成したステートマシン用のIAMポリシー(cm-hirai-notify-transcription-policy)を追加で適用します。
EventBridgeルール作成
音声ファイル保存用S3バケット(cm-hirai-audio-for-transcription)に、拡張子WAVの音声ファイルがアップロードされたことをトリガーとして、ステートマシンを起動するEventBridgeルールを作成します。
ルール名を記入します。
イベントパターンは以下の通りです。.wav
ではない音声ファイルの拡張子の場合、適宜修正ください。
{
"source": ["aws.s3"],
"detail-type": ["Object Created"],
"detail": {
"bucket": {
"name": ["cm-hirai-audio-for-transcription"]
},
"object": {
"key": [{
"suffix": ".wav"
}]
}
}
}
ターゲットは、先程作成したステートマシンを指定します。
以上の設定でEventBridgeルールを作成します。これにより、指定したS3バケットに.wavファイルがアップロードされると、自動的にステートマシンが起動されます。
テスト
テストのため、S3バケットcm-hirai-audio-for-transcription
に、拡張子wavの音声ファイルをアップロードします。
すると、メールで以下の内容が送信されました。
【自動通知】音声ファイルの文字起こし完了
音声ファイルが保存されましたので、文字起こし内容をお知らせいたします。
■ トランスクリプションジョブ詳細
・TranscribeジョブとStep Functionsステートマシン実行名: ee9c2644-ab6b-4da0-80b7-203521bb751a
・音声ファイル: s3://cm-hirai-audio-for-transcription/test1.wav
・文字起こしテキストファイル: s3://cm-hirai-transcription-output/ee9c2644-ab6b-4da0-80b7-203521bb751a.json
■ 文字起こし内容
あこんにちは。もしもし?クラスメソッドテテストです
■ 注意事項
1. 上記の文字起こし内容は自動生成されたものです。正確性を要する場合は、音声ファイルの内容をご確認ください。
2. 音声ファイルと文字起こしテキストファイルは、それぞれ指定されたS3バケット内に保存されています。必要に応じてダウンロードしてご利用ください。
本通知は自動生成されています。
ご不明な点やお問い合わせは、システム管理者までご連絡ください。
--
If you wish to stop receiving notifications from this topic, please click or visit the link below to unsubscribe:
https://sns.ap-northeast-1.amazonaws.com/unsubscribe.html?SubscriptionArn=arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:cm-hirai:xxxxx&Endpoint=test@example.com
Please do not reply directly to this email. If you have any questions or comments regarding this email, please contact us at https://aws.amazon.com/support
メール本文のうちIf you wish to stop receiving~~~略
は、デフォルトで送信されます。
最後
本記事では、AWS Step Functionsを利用して、S3バケットに音声ファイルが保存されるたびにAmazon Transcribeで文字起こしを行い、その内容をメールで送信するシステムの構築方法を解説しました。
この仕組みを応用すれば、Amazon Connectで録音した音声ファイルがS3バケットに保存されたことをトリガーに、自動で文字起こしを行い、その内容をメールで送信するといった運用が可能になります。
参考